from object import Object
from eventServer import eventServer
from textureServer import textureServer
from vec3 import Vec3
import math
import yaml

from OpenGL.GL import *

cubeBatches = {}
cubeLists = {}

def cubePreRender(cmd, args):
    for key in cubeBatches.iterkeys():
        cubeBatches[key] = []
    
def cubePostRender(cmd, args):
    #print len(cubeBatches.keys()), "batches", sum([len(data) for data in cubeBatches.values()]), "items"
    
    for renderContext, renderDataList in cubeBatches.iteritems():
        color, texture = renderContext
        
        glColor3f(color[0],color[1],color[2])
        textureServer.bindTexture(texture)
        
        #print "batch", renderContext
        
        for renderData in renderDataList:
            pos, rot, scale, tiles, face = renderData
            #print "data", renderData
            
            glPushMatrix()
            
            pos.translate()
            glRotatef(math.degrees(rot),0,0,1)
            (scale * -0.5).translate()
            if face == 'left':
                Vec3(scale.x,0,0).translate()
                Vec3(-1,1,1).scale()
            scale.scale()
            
            if cubeLists.has_key(tiles):
                #print "list", cubeLists[tiles]
                glCallList(cubeLists[tiles])
                
            else:
                dispList = glGenLists(1)
                glNewList(dispList,GL_COMPILE_AND_EXECUTE)
                cubeLists[tiles] = dispList
                #print "gen", dispList
            
                glBegin(GL_QUADS)
                
                #top
                glTexCoord2f(0,0)
                glVertex3f(1,1,0)
                glTexCoord2f(0,tiles)
                glVertex3f(0,1,0)
                glTexCoord2f(tiles,tiles)
                glVertex3f(0,1,1)
                glTexCoord2f(tiles,0)
                glVertex3f(1,1,1)
                
                #bottom
                glTexCoord2f(0,0)
                glVertex3f(1,0,1)
                glTexCoord2f(0,tiles)
                glVertex3f(0,0,1)
                glTexCoord2f(tiles,tiles)
                glVertex3f(0,0,0)
                glTexCoord2f(tiles,0)
                glVertex3f(1,0,0)
                
                #front
                glTexCoord2f(tiles,0)
                glVertex3f(1,1,1)
                glTexCoord2f(0,0)
                glVertex3f(0,1,1)
                glTexCoord2f(0,tiles)
                glVertex3f(0,0,1)
                glTexCoord2f(tiles,tiles)
                glVertex3f(1,0,1)
                
                #back
                glTexCoord2f(0,0)
                glVertex3f(1,0,0)
                glTexCoord2f(0,tiles)
                glVertex3f(0,0,0)
                glTexCoord2f(tiles,tiles)
                glVertex3f(0,1,0)
                glTexCoord2f(tiles,0)
                glVertex3f(1,1,0)
                
                #right
                glTexCoord2f(0,0)
                glVertex3f(0,1,1)
                glTexCoord2f(0,tiles)
                glVertex3f(0,1,0)
                glTexCoord2f(tiles,tiles)
                glVertex3f(0,0,0)
                glTexCoord2f(tiles,0)
                glVertex3f(0,0,1)
                
                #left
                glTexCoord2f(0,0)
                glVertex3f(1,1,0)
                glTexCoord2f(0,tiles)
                glVertex3f(1,1,1)
                glTexCoord2f(tiles,tiles)
                glVertex3f(1,0,1)
                glTexCoord2f(tiles,0)
                glVertex3f(1,0,0)
                
                glEnd()
                
                glEndList()
            
            glPopMatrix()
        
        glColor3f(1,1,1)
        textureServer.unbindTexture()
        
eventServer.register("preRender",cubePreRender)
eventServer.register("postRender",cubePostRender)

class Cube(Object):
    def __init__(self):
        Object.__init__(self)
        
        self.defaultVar("pos",Vec3())
        self.defaultVar("scale",Vec3(1,1,1))
        self.defaultVar("texture","")
        self.defaultVar("rot",0)
        self.defaultVar("shown",True)
        self.defaultVar("tiles",1.0)
        self.defaultVar("highlight",False)
        self.defaultVar("face","right")
        
        eventServer.register("render",self.render)
        
        self.displayLists = {}
        self.animationData = None
        self.animationPos = 1
        self.animationDir = 1
        self.animationStartTime = None
        
    def render(self, cmd, args):
        if not self.getVar("shown"):
            return
        
        color = (1,1,1)
        if self.getVar("highlight"):
            color = (1,0,0)
            
        if self.hasVar("animation") and self.hasVar("animationFamily"):
            animation = self.getVar("animation")
            animationFamily = self.getVar("animationFamily")
            
            #print "animation", animation, "family", animationFamily
            
            if not self.animationData:
                self.animationData = yaml.load(open('tex/%s/animations.yml' % animationFamily))
                
                print "loading animation family", animationFamily
                
                for animation in self.animationData.iterkeys():
                    print "animation", animation
                    
                    frame = 1
                    while textureServer.bindTexture("%s/Sprite_%s%d" % (animationFamily,animation,frame)):
                        frame += 1
                
            if self.animationData.has_key(animation):
                
                time = args['time']
                dtime = args['dtime']
                
                if self.animationData[animation].has_key('type'):
                    animationType = self.animationData[animation]['type']
                else:
                    animationType = 'loop'
                    
                if self.animationData[animation].has_key('frameTime'):
                    animationType = self.animationData[animation]['frameTime']
                else:
                    frameTime = 1.2
                    
                if not self.animationStartTime:
                    self.animationStartTime = time
                    
                if animationType in ('loop','once') and self.animationDir != 1:
                    self.animationDir = 1
                    
                if time - self.animationStartTime > frameTime:
                    self.animationPos += self.animationDir
                    
                texture = '%s/Sprite_%s%d' % (animationFamily,animation,self.animationPos)
                    
                if not textureServer.bindTexture(texture):
                    if animationType == 'loop':
                        self.animationPos = 1
                    elif animationType == 'once':
                        self.animationPos -= 1
                    elif animationType == 'bounce':
                        self.animationDir *= -1
                        self.animationPos += self.animationDir * 2
                    
                    texture = '%s/Sprite_%s%d' % (animationFamily,animation,self.animationPos)
                    
                #print "animation texture", texture
                    
            else:
                texture = self.getVar("texture")
        else:
            texture = self.getVar("texture")
        
        renderContext = color, texture
        
        pos = self.getVar("pos")
        rot = self.getVar("rot")
        scale = self.getVar("scale")
        tiles = self.getVar("tiles")
        face = self.getVar("face")
        
        renderData = pos, rot, scale, tiles, face
        
        if not cubeBatches.has_key(renderContext):
            cubeBatches[renderContext] = []
        cubeBatches[renderContext].append(renderData)
